package org.codehaus.activemq.store.jdbm;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.jms.JMSException;
import javax.transaction.xa.XAException;
import jdbm.btree.BTree;
import jdbm.helper.Tuple;
import jdbm.helper.TupleBrowser;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.activemq.message.ActiveMQXid;
import org.codehaus.activemq.service.Transaction;
import org.codehaus.activemq.service.TransactionManager;
import org.codehaus.activemq.store.PreparedTransactionStore;

public class JdbmPreparedTransactionStore
  implements PreparedTransactionStore
{
  private static final Log log = LogFactory.getLog(JdbmPreparedTransactionStore.class);
  private BTree database;

  public JdbmPreparedTransactionStore(BTree database)
  {
    this.database = database;
  }

  public ActiveMQXid[] getXids() throws XAException {
    try {
      List list = new ArrayList();
      Tuple tuple = new Tuple();
      TupleBrowser iter = this.database.browse();
      while (iter.getNext(tuple)) {
        list.add(tuple.getKey());
      }
      ActiveMQXid[] answer = new ActiveMQXid[list.size()];
      list.toArray(answer);
      return answer;
    } catch (IOException e) {
    	 throw new XAException("Failed to recover Xids. Reason: " + e);
    }
   
  }

  public void remove(ActiveMQXid xid) throws XAException
  {
    try {
      this.database.remove(xid);
    }
    catch (IOException e) {
      throw new XAException("Failed to remove: " + xid + ". Reason: " + e);
    }
  }

  public void put(ActiveMQXid xid, Transaction transaction) throws XAException {
    try {
      this.database.insert(xid, transaction, true);
    }
    catch (IOException e) {
      throw new XAException("Failed to add: " + xid + " for transaction: " + transaction + ". Reason: " + e);
    }
  }

  public void loadPreparedTransactions(TransactionManager transactionManager) throws XAException {
    log.info("Recovering prepared transactions");
    try
    {
      Tuple tuple = new Tuple();
      TupleBrowser iter = this.database.browse();
      while (iter.getNext(tuple)) {
        ActiveMQXid xid = (ActiveMQXid)tuple.getKey();
        Transaction transaction = (Transaction)tuple.getValue();
        transactionManager.loadTransaction(xid, transaction);
      }
    }
    catch (IOException e) {
      log.error("Failed to recover prepared transactions: " + e, e);
      throw new XAException("Failed to recover prepared transactions. Reason: " + e);
    }
  }

  public void start()
    throws JMSException
  {
  }

  public void stop()
    throws JMSException
  {
  }
}